package com.sg.elastic.core;

import java.io.IOException;
import java.util.Collections;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.http.HttpEntity;
import org.apache.http.HttpStatus;
import org.apache.http.entity.ContentType;
import org.apache.http.entity.StringEntity;
import org.apache.http.util.EntityUtils;
import org.elasticsearch.client.Response;
import org.elasticsearch.client.RestClient;
import org.elasticsearch.search.builder.SearchSourceBuilder;

import com.sg.elastic.core.support.HitConvertor;

/**
 * Created by yanlei on 17/5/23.
 */
public class ElasticTemplate implements ElasticOperations {

    protected final Log logger = LogFactory.getLog(getClass());

    private RestClient restClient;

    @Override
    public boolean index(String index, String type, String id, String json) throws IOException {
        if (logger.isDebugEnabled()) {
            logger.debug(
                    "index param: index [" + index + "], type [" + type + "], id [" + id + "], json [" + json + "]");
        }
        if (index == null) {
            throw new IllegalArgumentException("index must not be null");
        }
        if (type == null) {
            throw new IllegalArgumentException("type must not be null");
        }
        if (id == null) {
            throw new IllegalArgumentException("id must not be null");
        }
        if (json == null) {
            throw new IllegalArgumentException("json must not be null");
        }

        HttpEntity httpEntity = new StringEntity(json, ContentType.APPLICATION_JSON);
        String indexEndPoint = new StringBuffer()
                .append("/").append(index)
                .append("/").append(type)
                .append("/").append(id)
                .toString();

        Response response = restClient.performRequest("PUT",
                indexEndPoint,
                Collections.<String, String>emptyMap(),
                httpEntity);

        int statusCode = response.getStatusLine().getStatusCode();

        if (logger.isDebugEnabled()) {
            logger.debug("index result: requestLine [" + response.getRequestLine() + "], statusLine [" + response
                    .getStatusLine() + "]");
        }

        return statusCode == HttpStatus.SC_OK;
    }

    @Override
    public boolean index(String index, String type, String json) throws IOException {
        HttpEntity httpEntity = new StringEntity(json, ContentType.APPLICATION_JSON);
        String indexEndPoint = new StringBuffer()
                .append("/").append(index)
                .append("/").append(type)
                .toString();

        Response response = restClient.performRequest("PUT",
                indexEndPoint,
                Collections.<String, String>emptyMap(),
                httpEntity);

        int statusCode = response.getStatusLine().getStatusCode();

        return statusCode == HttpStatus.SC_OK || statusCode == HttpStatus.SC_CREATED;
    }

    @Override
    public <T> T search(String index, String type, SearchSourceBuilder builder, HitConvertor<T> convertor)
            throws IOException {

        HttpEntity httpEntity = new StringEntity(builder.toString(), ContentType.APPLICATION_JSON);

        String searchEndPoint = new StringBuffer()
                .append("/").append(index)
                .append("/").append(type)
                .append("/_search")
                .toString();

        Response response = restClient.performRequest("GET",
                searchEndPoint,
                Collections.<String, String>emptyMap(),
                httpEntity);

        String originReponseLine = EntityUtils.toString(response.getEntity());

        T result = convertor.convert(originReponseLine);
        return result;
    }

    public RestClient getRestClient() {
        return restClient;
    }

    public void setRestClient(RestClient restClient) {
        this.restClient = restClient;
    }
}
